﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Data;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using IssueVision.Common;
using IssueVision.EntityModel;

namespace IssueVision.ViewModel
{
    [Export(ViewModelTypes.AuditIssueViewModel, typeof(ViewModelBase))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class AuditIssueViewModel : ViewModelBase
    {
        #region "Private Data Members"
        private IIssueVisionModel _issueVisionModel;
        #endregion "Private Data Members"

        #region "Constructor"
        [ImportingConstructor]
        public AuditIssueViewModel(IIssueVisionModel issueVisionModel)
        {
            _issueVisionModel = issueVisionModel;

            // set up event handling
            _issueVisionModel.GetIssueTypesCompleted += _issueVisionModel_GetIssueTypesCompleted;
            _issueVisionModel.GetResolutionsCompleted += _issueVisionModel_GetResolutionsCompleted;
            _issueVisionModel.GetStatusesCompleted += _issueVisionModel_GetStatusesCompleted;
            _issueVisionModel.GetSubStatusesCompleted += _issueVisionModel_GetSubStatusesCompleted;
            _issueVisionModel.GetUsersCompleted += _issueVisionModel_GetUsersCompleted;
            _issueVisionModel.GetIssueHistoryByIssueIDCompleted += _issueVisionModel_GetIssueHistoryByIssueIDCompleted;

            // load issue type entries
            _issueVisionModel.GetIssueTypesAsync();
            //load resolution entries
            _issueVisionModel.GetResolutionsAsync();
            // load status entries
            _issueVisionModel.GetStatusesAsync();
            // load substatus entries
            _issueVisionModel.GetSubStatusesAsync();
            // load user entries
            _issueVisionModel.GetUsersAsync();
        }
        #endregion "Constructor"

        #region "ICleanup interface implementation"
        public override void Cleanup()
        {
            if (_issueVisionModel != null)
            {
                // unregister all events
                _issueVisionModel.GetIssueTypesCompleted -= _issueVisionModel_GetIssueTypesCompleted;
                _issueVisionModel.GetResolutionsCompleted -= _issueVisionModel_GetResolutionsCompleted;
                _issueVisionModel.GetStatusesCompleted -= _issueVisionModel_GetStatusesCompleted;
                _issueVisionModel.GetSubStatusesCompleted -= _issueVisionModel_GetSubStatusesCompleted;
                _issueVisionModel.GetUsersCompleted -= _issueVisionModel_GetUsersCompleted;
                _issueVisionModel.GetIssueHistoryByIssueIDCompleted -= _issueVisionModel_GetIssueHistoryByIssueIDCompleted;
                _issueVisionModel = null;
            }
            // set properties back to null
            _issueHistories = null;
            IssueHistoryItem = null;
            IssueTypeEntries = null;
            PlatformEntries = null;
            ResolutionEntriesWithNull = null;
            StatusEntries = null;
            SubstatusEntriesWithNull = null;
            UserEntries = null;
            UserEntriesWithNull = null;
            // unregister any messages for this ViewModel
            base.Cleanup();
        }
        #endregion "ICleanup interface implementation"

        #region "Public Properties"

        public long CurrentIssueID { get; set; }

        private ObservableCollection<IssueHistory> _issueHistories;

        public CollectionViewSource IssueHistorySource { get; private set; }

        private IssueHistory _issueHistoryItem;

        public IssueHistory IssueHistoryItem
        {
            get { return _issueHistoryItem; }
            private set
            {
                if (!ReferenceEquals(_issueHistoryItem, value))
                {
                    _issueHistoryItem = value;
                    RaisePropertyChanged("IssueHistoryItem");
                }
            }
        }

        private IEnumerable<byte> _priorityEntries;

        public IEnumerable<byte> PriorityEntries
        {
            get
            {
                if (_priorityEntries == null)
                {
                    List<byte> priorityList = new List<byte>();
                    for (byte i = IssueVisionServiceConstant.HighestPriority; i <= IssueVisionServiceConstant.LowestPriority; i++)
                    {
                        priorityList.Add(i);
                    }
                    _priorityEntries = priorityList.AsEnumerable();
                }
                return _priorityEntries;
            }
        }

        private IEnumerable<byte> _severityEntries;

        public IEnumerable<byte> SeverityEntries
        {
            get
            {
                if (_severityEntries == null)
                {
                    List<byte> severityList = new List<byte>();
                    for (byte i = IssueVisionServiceConstant.HighestSeverity; i <= IssueVisionServiceConstant.LowestSeverity; i++)
                    {
                        severityList.Add(i);
                    }
                    _severityEntries = severityList.AsEnumerable();
                }
                return _severityEntries;
            }
        }

        private IEnumerable<IssueType> _issueTypeEntries;

        public IEnumerable<IssueType> IssueTypeEntries
        {
            get { return _issueTypeEntries; }
            private set
            {
                if (!ReferenceEquals(_issueTypeEntries, value))
                {
                    _issueTypeEntries = value;
                    RaisePropertyChanged("IssueTypeEntries");
                }
            }
        }

        private IEnumerable<Platform> _platformEntries;

        public IEnumerable<Platform> PlatformEntries
        {
            get { return _platformEntries; }
            private set
            {
                if (!ReferenceEquals(_platformEntries, value))
                {
                    _platformEntries = value;
                    RaisePropertyChanged("PlatformEntries");
                }
            }
        }

        private IEnumerable<Resolution> _resolutionEntriesWithNull;

        public IEnumerable<Resolution> ResolutionEntriesWithNull
        {
            get { return _resolutionEntriesWithNull; }
            private set
            {
                if (!ReferenceEquals(_resolutionEntriesWithNull, value))
                {
                    _resolutionEntriesWithNull = value;
                    RaisePropertyChanged("ResolutionEntriesWithNull");
                }
            }
        }

        private IEnumerable<Status> _statusEntries;

        public IEnumerable<Status> StatusEntries
        {
            get { return _statusEntries; }
            private set
            {
                if (!ReferenceEquals(_statusEntries, value))
                {
                    _statusEntries = value;
                    RaisePropertyChanged("StatusEntries");
                }
            }
        }

        private IEnumerable<SubStatus> _substatusEntriesWithNull;

        public IEnumerable<SubStatus> SubstatusEntriesWithNull
        {
            get { return _substatusEntriesWithNull; }
            private set
            {
                if (!ReferenceEquals(_substatusEntriesWithNull, value))
                {
                    _substatusEntriesWithNull = value;
                    RaisePropertyChanged("SubstatusEntriesWithNull");
                }
            }
        }

        private IEnumerable<User> _userEntries;

        public IEnumerable<User> UserEntries
        {
            get { return _userEntries; }
            private set
            {
                if (!ReferenceEquals(_userEntries, value))
                {
                    _userEntries = value;
                    RaisePropertyChanged("UserEntries");
                }
            }
        }

        private IEnumerable<User> _userEntriesWithNull;

        public IEnumerable<User> UserEntriesWithNull
        {
            get { return _userEntriesWithNull; }
            private set
            {
                if (!ReferenceEquals(_userEntriesWithNull, value))
                {
                    _userEntriesWithNull = value;
                    RaisePropertyChanged("UserEntriesWithNull");
                }
            }
        }

        #endregion "Public Properties"

        #region "Public Commands"

        private RelayCommand<SelectionChangedEventArgs> _selectionChangedCommand;

        public RelayCommand<SelectionChangedEventArgs> SelectionChangedCommand
        {
            get
            {
                if (_selectionChangedCommand == null)
                {
                    _selectionChangedCommand = new RelayCommand<SelectionChangedEventArgs>(
                        e => OnSelectionChangedCommand(e));
                }
                return _selectionChangedCommand;
            }
        }

        private void OnSelectionChangedCommand(SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count == 1)
            {
                var enumerator = e.AddedItems.GetEnumerator();
                enumerator.MoveNext();
                // set the new selected IssueHistory item
                IssueHistoryItem = (IssueHistory)enumerator.Current;
                // set PlatformEntries
                if (IssueHistoryItem != null && IssueHistoryItem.Platform != null)
                {
                    List<Platform> platformList = new List<Platform> {IssueHistoryItem.Platform};
                    PlatformEntries = platformList.AsEnumerable();
                }
                else
                {
                    List<Platform> platformList = new List<Platform>();
                    PlatformEntries = platformList.AsEnumerable();
                }
            }
        }

        private RelayCommand _auditIssueCommand;

        public RelayCommand AuditIssueCommand
        {
            get
            {
                if (_auditIssueCommand == null)
                {
                    _auditIssueCommand = new RelayCommand(
                        () => OnAuditIssueCommand());
                }
                return _auditIssueCommand;
            }
        }

        private void OnAuditIssueCommand()
        {
            try
            {
                if (!_issueVisionModel.IsBusy)
                {
                    _issueVisionModel.GetIssueHistoryByIssueIDAsync(CurrentIssueID);
                }
            }
            catch (Exception ex)
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(ex);
            }
        }

        #endregion "Public Commands"

        #region "Private Methods"

        /// <summary>
        /// Event handler for GetIssueTypesCompleted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _issueVisionModel_GetIssueTypesCompleted(object sender, ResultsArgs<IssueType> e)
        {
            if (!e.HasError)
            {
                IssueTypeEntries = e.Results.OrderBy(g => g.Name);
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        /// <summary>
        /// Event handler for GetResolutionsCompleted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _issueVisionModel_GetResolutionsCompleted(object sender, ResultsArgs<Resolution> e)
        {
            if (!e.HasError)
            {
                // create a new resolution list with the first item of null Name
                List<Resolution> resolutionList = e.Results.ToList();
                resolutionList.Add(new Resolution());
                ResolutionEntriesWithNull = resolutionList.OrderBy(g => g.Name).AsEnumerable();
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        /// <summary>
        /// Event handler for GetStatusesCompleted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _issueVisionModel_GetStatusesCompleted(object sender, ResultsArgs<Status> e)
        {
            if (!e.HasError)
            {
                StatusEntries = e.Results.OrderBy(g => g.StatusID);
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        /// <summary>
        /// Event handler for GetSubStatusesCompleted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _issueVisionModel_GetSubStatusesCompleted(object sender, ResultsArgs<SubStatus> e)
        {
            if (!e.HasError)
            {
                // create a new substatus list with the first item of null Name
                List<SubStatus> substatusList = e.Results.ToList();
                substatusList.Add(new SubStatus());
                SubstatusEntriesWithNull = substatusList.OrderBy(g => g.Name).AsEnumerable();
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        /// <summary>
        /// Event handler for GetUsersCompleted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _issueVisionModel_GetUsersCompleted(object sender, ResultsArgs<User> e)
        {
            if (!e.HasError)
            {
                UserEntries = e.Results.OrderBy(g => g.Name);
                // create a new user list with the first item of null user name
                List<User> userList = e.Results.ToList();
                userList.Add(new User());
                UserEntriesWithNull = userList.OrderBy(g => g.Name).AsEnumerable();
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        /// <summary>
        /// Event handler for GetIssueHistoryByIssueIDCompleted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _issueVisionModel_GetIssueHistoryByIssueIDCompleted(object sender, ResultsArgs<IssueHistory> e)
        {
            if (!e.HasError)
            {
                _issueHistories = new ObservableCollection<IssueHistory>(e.Results.OrderBy(g => g.DateCreated));

                IssueHistorySource = new CollectionViewSource {Source = _issueHistories};
                // notify that IssueHistorySource has changed
                RaisePropertyChanged("IssueHistorySource");

                // set the first row as the current IssueHistory item
                if (_issueHistories.Count >= 1)
                {
                    IssueHistoryItem = _issueHistories.First();
                    // set PlatformEntries
                    if (IssueHistoryItem.Platform != null)
                    {
                        List<Platform> platformList = new List<Platform> {IssueHistoryItem.Platform};
                        PlatformEntries = platformList.AsEnumerable();
                    }
                    else
                    {
                        List<Platform> platformList = new List<Platform>();
                        PlatformEntries = platformList.AsEnumerable();
                    }
                }
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        #endregion "Private Methods"
    }
}
